//
// Ishtar C++ Utility Library
//
// Task Facility - Thread Pool Implementation
//

#include <Ishtar/Pch.h>

#include <Ishtar/Task/ThreadPoolImpl.h>


namespace Ishtar
{

namespace Task
{

///////////////////////////////////////////////////////////////////////////////
//
// Thread Pool
//

ThreadPoolImpl::ThreadPoolImpl( const std::string& name, Uint numThreads, ThreadPool& host )
    : m_name( name )
    , m_host( host )
    , m_shutdown( false )
{
    for ( Uint i = 0; i < numThreads; ++ i )
    {
        m_threads.push_back( new PooledThread( this, i ));
        m_threads[i].Start();
        m_readyThreads.Push( &m_threads[i] );
    }
}


//ThreadPoolImpl::~ThreadPoolImpl()
//{
//    if ( !m_shutdown )
//    {
//        ISHTAR_TRACE_WARN_HERE( "Destroy a thread pool before shutdown it" );
//        ISHTAR_TRACE_INFO( "  name: %s", m_name );
//
//        // REMARKS: don't relay on the destructor to shutdown a thread pool.
//        //          here is only a REMEDY.
//        
//        this->Shutdown();
//    }
//}
//
//
//void ThreadPoolImpl::Shutdown()
//{
//    ISHTAR_ASSERT( !m_shutdown );
//
//    m_shutdown = true;
//    
//    while ( m_readyThreads.UnsafeSize() != m_threads.size()
//         || !m_readyWorks.IsEmpty() )
//    {
//        Thread::Sleep( 100 );
//    }
//    
//    for ( Uint i = 0; i < m_threads.size(); ++ i )
//    {
//        m_threads[i].Stop();
//    }
//    
//    for ( Uint i = 0; i < m_threads.size(); ++ i )
//    {
//        m_threads[i].Join();
//    }
//}
//
//
//void ThreadPoolImpl::SubmitWork( const Work& w )
//{
//    if ( m_shutdown )
//    {
//        {
//            ISHTAR_TRACE_WARN_HERE( "Thread pool has been shutdown" );
//            ISHTAR_TRACE_INFO( "  threadPoolName: %s, workName: %s", m_name, w.Name() );
//        }        
//        
//        w.m_impl->AbortRun();
//        return;
//    }
//
//    w.m_impl->Setup( this );
//}
//
//
//void ThreadPoolImpl::AddReadyWork( const WorkImplPtr& work )
//{
//    m_numWaitingWorks.Increment();
//
//    if ( m_readyWorks.IsEmpty() )
//    {
//        PooledThread* thread = NULL;
//        if ( m_readyThreads.TryPop( thread ))
//        {
//            this->WakeThreadToExecuteWork( thread, work );
//            return;
//        }
//    }
//    
//    m_readyWorks.Push( work );
//    
//    if ( !m_readyThreads.IsEmpty() )
//    {
//        this->DispatchOne();
//    }
//}
//
//
//void ThreadPoolImpl::AddReadyThread( PooledThread* thread )
//{
//    WorkImplPtr work;
//    if ( m_readyWorks.TryPop( work ))
//    {
//        this->WakeThreadToExecuteWork( thread, work );
//        return;
//    }
//
//    m_readyThreads.Push( thread );
//    
//    if ( !m_readyWorks.IsEmpty() )
//    {
//        this->DispatchOne();
//    }
//}
//
//
//void ThreadPoolImpl::DispatchOne()
//{
//    PooledThread* thread = NULL;
//    if ( m_readyThreads.TryPop( thread ))
//    {
//        WorkImplPtr work;
//        if ( m_readyWorks.TryPop( work ))
//        {
//            this->WakeThreadToExecuteWork( thread, work );
//            return;
//        }
//        else
//        {
//            m_readyThreads.Push( thread );
//        }
//    }
//}
//
//
//void ThreadPoolImpl::WakeThreadToExecuteWork( PooledThread* thread, const WorkImplPtr& work )
//{
//    m_numWaitingWorks.Decrement();
//    thread->Wake( work );
//}
//
//
////
//// Bridging
////
//
//void ThreadPool::Startup( const std::string& name, Uint numThreads )
//{
//    ISHTAR_ASSERT( !m_impl );
//    
//    m_impl.reset( new ThreadPoolImpl( name, numThreads, *this ));
//}
//
//
//void ThreadPool::Shutdown()
//{
//    if ( !m_impl ) { return; }
//
//    m_impl->Shutdown();
//}
//
//
//void ThreadPool::SubmitWork( const Work& w )
//{
//    ISHTAR_ASSERT( m_impl );
//    ISHTAR_ASSERT( !w.IsEmpty() );
//
//    m_impl->SubmitWork( w );
//}
//
//
//Uint ThreadPool::GetNumWaitingWorks() const
//{
//    ISHTAR_ASSERT( m_impl );
//
//    return m_impl->GetNumWaitingWorks();
//}
//
//
//WorkExecutorImpl* ThreadPool::GetImpl() const
//{
//    return m_impl.GetRawPointer();
//}


///////////////////////////////////////////////////////////////////////////////

} // namespace Task

} // namespace Ishtar
